﻿// Inner Kit 通用工具库
// 字符串操作
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 用于字符串操作的一些快捷方式
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-04-14

#include "kstring.h"
#include <Windows.h>
#include <codecvt>
#include <locale>
#include <string>

namespace ikit {

int strcasecmp(const char* s1, const char* s2) {
  int c1, c2;

  do {
    c1 = tolower(*s1);
    c2 = tolower(*s2);
    s1++;
    s2++;
  } while (c1 == c2 && c1 && c2);

  return c1 - c2;
}

// 复制一个字符串（会重新分配内存）
char* str_copy(const char* str) {
  // 常规检查，如果是空，则返回空
  if (str == nullptr) {
    return nullptr;
  }

  int len = static_cast<int>(strlen(str)) + 1;
  char* new_str = (char*)malloc(len);
  // 这里的LEN会直接复制最后一个'\0'结束符，所以不用再配置'\0'结束符
  if (new_str != nullptr) {
    memcpy(new_str, str, len);
  }
  return new_str;
}

std::string replace_with_CrLf(const std::string& input) {
  std::string result = input;
  std::string::size_type pos = 0;
  while ((pos = result.find("\n", pos)) != std::string::npos) {
    result.replace(pos, 1, "\r\n");
    pos += 2; // 移动到新插入的 "\r\n" 之后，避免替换掉 "\r"
  }
  return result;
}

int index_of(const char* text, const char* substr) {
  const char* pos = strstr(text, substr);
  return pos ? (int)(pos - text) : -1;
}

std::string utf8_to_gbk(const std::string_view& utf8_str) {
  // 将UTF-8字符串转换为宽字符串
  std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
  std::wstring wide_str = utf8_conv.from_bytes(utf8_str.data());

  // 将宽字符串转换为GBK编码的字符串
  const char* GBK_LOCALE_NAME = ".936"; // GBK在Windows下的locale名称
  std::wstring_convert<std::codecvt_byname<wchar_t, char, mbstate_t>> gbk_conv(
      new std::codecvt_byname<wchar_t, char, mbstate_t>(GBK_LOCALE_NAME));
  std::string gbk_str = gbk_conv.to_bytes(wide_str);

  return gbk_str;
}
std::string gbk_to_utf8(const std::string_view& gbk_str) {
  // 先将GBK转换为宽字符（UTF-16）
  int len = MultiByteToWideChar(CP_ACP, 0, gbk_str.data(), -1, nullptr, 0);
  if (len == 0) {
    throw std::runtime_error("MultiByteToWideChar failed");
  }
  std::wstring wstr(len, 0);
  MultiByteToWideChar(CP_ACP, 0, gbk_str.data(), -1, &wstr[0], len);

  // 再将宽字符转换为UTF-8
  len = WideCharToMultiByte(
      CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
  if (len == 0) {
    throw std::runtime_error("WideCharToMultiByte failed");
  }
  std::string utf8_str(len, 0);
  WideCharToMultiByte(
      CP_UTF8, 0, wstr.c_str(), -1, &utf8_str[0], len, nullptr, nullptr);
  return utf8_str;
}

std::wstring to_wide(const std::string_view& str) {
  /*WCHAR buffer[512];
  MultiByteToWideChar(CP_ACP, 0, str.data(), -1, buffer, 512);
  return std::wstring(buffer);*/
  int len = MultiByteToWideChar(CP_UTF8, 0, str.data(), -1, NULL, 0);
  std::wstring wstr(len, 0);
  MultiByteToWideChar(CP_UTF8, 0, str.data(), -1, &wstr[0], len);
  return wstr;
}

std::string from_wide(const std::wstring_view& wstr) {
  if (wstr.empty())
    return std::string();

  int len = WideCharToMultiByte(
      CP_ACP, 0, wstr.data(), (int)wstr.size(), NULL, 0, NULL, NULL);
  if (len == 0)
    return std::string();

  std::string result(len, 0);
  WideCharToMultiByte(
      CP_ACP, 0, wstr.data(), (int)wstr.size(), &result[0], len, NULL, NULL);
  return result;
}

// std::wstring StringToWString(const std::string& str) {
//   int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
//   std::wstring wstr(len, 0);
//   MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &wstr[0], len);
//   return wstr;
// }

const char* onoff(bool is_on) { return is_on ? ON_STRING : OFF_STRING; }

const char* truefalse(bool is_true) {
  return is_true ? TRUE_STRING : FALSE_STRING;
}

const char* pick(bool is_true, const char* true_text, const char* false_text) {
  return is_true ? true_text : false_text;
}

std::pair<std::string_view, std::string_view> split_element(
    const std::string& str, char delimiter) {
  size_t pos = str.find(delimiter);
  if (pos != std::string::npos) {
    return {std::string_view(str.data(), pos),
        std::string_view(str.data() + pos + 1, str.size() - pos - 1)};
  } else {
    return {str, ""};
  }
}

} // namespace ikit